package com.glSto.controller;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.net.ssl.*;
import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.sql.Date;
import java.util.*;
import javax.crypto.Cipher;
import java.util.Base64;

@RestController
@RequestMapping("/api/access-control")
public class AccessControlSystem_CBS {
    // 日志记录器
    private static final Logger mainDataLogger = LoggerFactory.getLogger("com.glSto.controller.AccessControlSystem.mainData");
    private static final Gson gson = new GsonBuilder()
            .setDateFormat("yyyy-MM-dd HH:mm:ss")  // 支持空格分隔的日期格式
            .create();

    // 数据库模板（通过Spring注入）
    @Autowired
    private JdbcTemplate jdbcTemplate;

    // ---------------------- 接口常量定义 ----------------------
    private static final String TOKEN_API_URL = "https://10.105.0.5:443/evo-apigw/evo-oauth/1.0.0/oauth/extend/token";
    private static final String PERSON_SUBSYSTEM_LIST_API_URL = "https://10.105.0.5:443/evo-apigw/evo-brm/1.2.0/person/subsystem/list-page";
    private static final String FIXED_CLIENT_ID = "wuyanggao";
    private static final String FIXED_CLIENT_SECRET = "42bec152-8f04-476a-9aec-e7d616ff3cb3";
    private static final String FIXED_GRANT_TYPE = "password";
    private static final String OAUTH_BEARER_PREFIX = "Bearer ";
    private static final int FIXED_PAGE_SIZE = 100;

    // ---------------------- HTTPS证书处理 ----------------------
    static {
        try {
            TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        public X509Certificate[] getAcceptedIssuers() { return null; }
                        public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {}
                        public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {}
                    }
            };
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            HostnameVerifier allHostsValid = (hostname, session) -> true;
            HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
        } catch (Exception e) {
            mainDataLogger.error("SSL初始化异常（影响HTTPS鉴权请求）", e);
            throw new RuntimeException("SSL初始化失败，无法发起OAuth 2.0鉴权请求", e);
        }
    }

    // ---------------------- 合并后的单一API接口 ----------------------

    /**
     * 人员数据同步综合接口
     * 一次调用完成：获取Token → 同步人员数据 → 返回结果
     * POST /api/access-control/sync-all
     */
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/AccessControlSystem_CBS")
    public Map<String, Object> syncAll(@RequestBody Map<String, Object> requestBody) {
        Map<String, Object> response = new HashMap<>();
        SyncResult result = new SyncResult();
        result.setStartTime(new Date(System.currentTimeMillis()));

        try {
            // 1. 验证请求参数
            String username = (String) requestBody.get("username");
            String password = (String) requestBody.get("password");
            Integer maxRangeId = requestBody.get("maxRangeId") != null ?
                    Integer.parseInt(requestBody.get("maxRangeId").toString()) : null;

            if (username == null || username.isEmpty() || password == null || password.isEmpty()) {
                result.setSuccess(false);
                result.setErrors(Collections.singletonList("用户名和密码不能为空"));
                response.put("success", false);
                response.put("data", result);
                return response;
            }

            // 2. 获取Access Token
            mainDataLogger.info("开始获取Access Token，用户：{}", username);
            TokenData tokenData = getOAuthAccessToken(username, password);
            result.setTokenInfo(tokenData);
            mainDataLogger.info("成功获取Access Token，有效期：{}秒", tokenData.getExpires_in());

            // 3. 同步人员数据
            mainDataLogger.info("开始同步人员数据，maxRangeId：{}", maxRangeId);
            SyncDetail syncDetail = queryPersonSubsystemListWithAutoPage(maxRangeId, tokenData.getAccess_token());

            // 4. 组装结果
            result.setSuccess(true);
            result.setSyncDetail(syncDetail);
            result.setEndTime(new Date(System.currentTimeMillis()));

            response.put("success", true);
            response.put("data", result);
            return response;

        } catch (Exception e) {
            mainDataLogger.error("同步流程异常", e);
            result.setSuccess(false);
            result.setErrors(Collections.singletonList("同步失败: " + e.getMessage()));
            result.setEndTime(new Date(System.currentTimeMillis()));

            response.put("success", false);
            response.put("data", result);
            return response;
        }
    }

    // ---------------------- 核心方法实现 ----------------------

    private TokenData getOAuthAccessToken(String username, String plainPassword) throws Exception {
        // 获取RSA公钥
        String publicKeyApi = "https://10.105.0.5:443/evo-apigw/evo-oauth/1.0.0/oauth/public-key";
        mainDataLogger.info("从接口获取RSA公钥：{}", publicKeyApi);
        String publicKeyResponse = sendHttpsGetRequest(publicKeyApi);
        String publicKey = extractPublicKey(publicKeyResponse);

        if (publicKey == null) {
            throw new RuntimeException("无法获取有效RSA公钥");
        }

        // RSA加密密码
        mainDataLogger.info("加密Token请求密码");
        String encryptedPassword = encrypt(plainPassword, publicKey);

        // 构造并发送Token请求
        TokenRequest tokenRequest = new TokenRequest(username, encryptedPassword, publicKey);
        String tokenResponseJson = sendHttpsPostWithOAuth(TOKEN_API_URL, tokenRequest, "TOKEN_REQUEST_NO_AUTH");
        TokenResponse tokenResponse = gson.fromJson(tokenResponseJson, TokenResponse.class);

        // 验证Token响应
        if (tokenResponse == null || !tokenResponse.isSuccess() || tokenResponse.getData() == null || tokenResponse.getData().getAccess_token() == null) {
            String errMsg = String.format("Token获取失败：success=%s，code=%s，errMsg=%s",
                    tokenResponse == null ? "null" : tokenResponse.isSuccess(),
                    tokenResponse == null ? "null" : tokenResponse.getCode(),
                    tokenResponse == null ? "null" : tokenResponse.getErrMsg());
            throw new RuntimeException(errMsg);
        }

        return tokenResponse.getData();
    }

    private SyncDetail queryPersonSubsystemListWithAutoPage(Integer maxRangeId, String accessToken) {
        SyncDetail detail = new SyncDetail();
        int currentPage = 1;
        boolean hasNextPage = true;
        List<String> errorMessages = new ArrayList<>();

        // 先清空中间表
        boolean clearSuccess = deleteZJB();
        if (!clearSuccess) {
            errorMessages.add("中间表清空失败");
            detail.setErrors(errorMessages);
            return detail;
        }

        while (hasNextPage) {
            try {
                // 构造分页请求
                PersonSubsystemListRequest personRequest = new PersonSubsystemListRequest(currentPage, maxRangeId);
                String responseJson = sendHttpsPostWithOAuth(PERSON_SUBSYSTEM_LIST_API_URL, personRequest, accessToken);
                PersonSubsystemListResponse personResponse = gson.fromJson(responseJson, PersonSubsystemListResponse.class);

                if (personResponse == null || !personResponse.isSuccess() || personResponse.getData() == null) {
                    String errMsg = String.format("第%d页查询失败：success=%s，code=%s，errMsg=%s",
                            currentPage,
                            personResponse == null ? "null" : personResponse.isSuccess(),
                            personResponse == null ? "null" : personResponse.getCode(),
                            personResponse == null ? "null" : personResponse.getErrMsg());
                    errorMessages.add(errMsg);
                    break;
                }

                PersonSubsystemData personData = personResponse.getData();
                int totalPage = personData.getTotalPage();
                int totalRows = personData.getTotalRows();
                PersonItem[] personItems = personData.getPageData();

                // 更新统计信息
                detail.setTotalPages(totalPage);
                detail.setTotalRecords(totalRows);

                if (personItems != null && personItems.length > 0) {
                    for (PersonItem person : personItems) {
                        try {
                            // 非空校验：避免核心字段null导致插入异常
                            if (person.getId() == 0 || person.getPaperNumber() == null || person.getPaperNumber().isEmpty()) {
                                throw new IllegalArgumentException("人员ID或证件号不能为空");
                            }

                            // 提取人员信息并插入数据库
                            boolean inserted = batchInsertDepartments(person);
                            if (inserted) {
                                detail.incrementSuccessCount();
                            } else {
                                detail.incrementFailedCount();
                                errorMessages.add("插入失败, 编码: " + person.getPaperNumber());
                            }
                        } catch (Exception e) {
                            detail.incrementFailedCount();
                            errorMessages.add("处理失败 (" + person.getPaperNumber() + "): " + e.getMessage());
                            mainDataLogger.error("处理人员数据异常（编码：{}）", person.getPaperNumber(), e);
                        }
                    }
                }

                // 分页控制
                if (currentPage < totalPage) {
                    currentPage++;
                } else {
                    hasNextPage = false;
                }

            } catch (Exception e) {
                mainDataLogger.error("第{}页查询异常", currentPage, e);
                errorMessages.add("第" + currentPage + "页查询异常: " + e.getMessage());
                break;
            }
        }

        detail.setErrors(errorMessages);
        return detail;
    }

    // 提取人员信息并插入数据库（修复日期处理+移除手动转义）
    private boolean batchInsertDepartments(PersonItem person) {
        try {
            // 1. 构造中间表插入SQL（预编译，?占位符）
            String zjbSql = "INSERT INTO MJXTJK_RY_ZJB (" +
                    "id, name, code, paperType, paperTypeName, paperNumber, paperAddress, " +
                    "departmentId, phone, email, age, birthday, sex, country, nation, " +
                    "nationName, selfCode, status, ownerCode, personBiosignatures, departmentList, " +
                    "create_time, update_time" +
                    ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, SYSDATE, SYSDATE)";

            // 2. 构造主表插入SQL（与中间表结构一致）
            String mainSql = "INSERT INTO MJXTJK_RY (" +
                    "id, name, code, paperType, paperTypeName, paperNumber, paperAddress, " +
                    "departmentId, phone, email, age, birthday, sex, country, nation, " +
                    "nationName, selfCode, status, ownerCode, personBiosignatures, departmentList, " +
                    "create_time, update_time" +
                    ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, SYSDATE, SYSDATE)";

            // 3. 处理参数（核心修复：生日字段转为java.sql.Date，避免字符串格式问题）
            Date birthday = null;
            if (person.getBirthday() != null) {
                birthday = new Date(person.getBirthday());
                mainDataLogger.debug("人员[{}]生日处理：时间戳={} → Date={}",
                        person.getPaperNumber(), person.getBirthday(), birthday);
            }

            // 生物特征数组 → JSON字符串
            String biosignatureJson = null;
            if (person.getPersonBiosignatures() != null && person.getPersonBiosignatures().length > 0) {
                biosignatureJson = gson.toJson(person.getPersonBiosignatures());
            }

            // 部门数组 → JSON字符串
            String departmentJson = null;
            if (person.getDepartmentList() != null && person.getDepartmentList().length > 0) {
                departmentJson = gson.toJson(person.getDepartmentList());
            }

            // selfCode：使用人员code
            String selfCode = person.getCode();

            // 4. 组装参数数组（顺序与SQL占位符严格对应）
            Object[] params = {
                    person.getId(),                  // 1. id
                    person.getName(),                // 2. name
                    person.getCode(),                // 3. code
                    person.getPaperType(),           // 4. paperType
                    person.getPaperTypeName(),       // 5. paperTypeName
                    person.getPaperNumber(),         // 6. paperNumber
                    person.getPaperAddress(),        // 7. paperAddress
                    person.getDepartmentId(),        // 8. departmentId
                    person.getPhone(),               // 9. phone
                    person.getEmail(),               // 10. email
                    person.getAge(),                 // 11. age
                    birthday,                        // 12. birthday（核心修复点）
                    person.getSex(),                 // 13. sex
                    person.getCountry(),             // 14. country
                    person.getNation(),              // 15. nation
                    person.getNationName(),          // 16. nationName
                    selfCode,                        // 17. selfCode
                    person.getStatus(),              // 18. status
                    person.getOwnerCode(),           // 19. ownerCode
                    biosignatureJson,                // 20. personBiosignatures
                    departmentJson                   // 21. departmentList
            };

            // 5. 检查主表是否存在该记录
            String checkSql = "SELECT COUNT(*) FROM MJXTJK_RY WHERE id = ?";
            Integer count = jdbcTemplate.queryForObject(checkSql, new Object[]{person.getId()}, Integer.class);

            // 6. 主表不存在则插入
            if (count == null || count == 0) {
                jdbcTemplate.update(mainSql, params);
                mainDataLogger.debug("主表插入成功，人员ID：{}，证件号：{}", person.getId(), person.getPaperNumber());
            }

            // 7. 插入中间表
            jdbcTemplate.update(zjbSql, params);
            mainDataLogger.debug("中间表插入成功，人员ID：{}，证件号：{}", person.getId(), person.getPaperNumber());

            return true;
        } catch (Exception e) {
            mainDataLogger.error("插入数据失败（人员编码：{}）", person.getPaperNumber(), e);
            return false;
        }
    }

    // 清空中间表
    private boolean deleteZJB() {
        try {
            String sql = "DELETE FROM MJXTJK_RY_ZJB";
            jdbcTemplate.update(sql);
            mainDataLogger.info("中间表MJXTJK_RY_ZJB清空完成");
            return true;
        } catch (Exception e) {
            mainDataLogger.error("删除中间表数据失败：" + e.getMessage(), e);
            return false;
        }
    }

    // ---------------------- HTTP请求方法 ----------------------

    private String sendHttpsPostWithOAuth(String apiUrl, Object requestParam, String accessToken) {
        StringBuilder response = new StringBuilder();
        HttpsURLConnection connection = null;
        OutputStream outputStream = null;
        InputStream inputStream = null;
        BufferedReader reader = null;

        try {
            URL url = new URL(apiUrl);
            connection = (HttpsURLConnection) url.openConnection();

            // 设置请求头
            if (!"TOKEN_REQUEST_NO_AUTH".equals(accessToken)) {
                connection.setRequestProperty("Authorization", OAUTH_BEARER_PREFIX + accessToken);
            }
            connection.setRequestMethod("POST");
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(8000);
            connection.setDoOutput(true);
            connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
            connection.setRequestProperty("Accept", "application/json");
            connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");

            // 发送请求体
            String rawJsonRequest = gson.toJson(requestParam);
            mainDataLogger.info("接口[{}]请求体：\n{}", apiUrl, rawJsonRequest);

            outputStream = connection.getOutputStream();
            outputStream.write(rawJsonRequest.getBytes(StandardCharsets.UTF_8));
            outputStream.flush();

            // 处理响应
            int responseCode = connection.getResponseCode();
            inputStream = (responseCode >= 200 && responseCode < 300) ?
                    connection.getInputStream() : connection.getErrorStream();

            // 记录错误状态码
            if (responseCode >= 300) {
                String errMsg = String.format("接口请求失败（%d）", responseCode);
                mainDataLogger.error(errMsg);
                response.append(errMsg).append("\n");
            }

            // 读取响应内容
            reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }

        } catch (IOException e) {
            mainDataLogger.error("接口[{}]请求异常", apiUrl, e);
            response.append("请求异常：").append(e.getMessage());
        } finally {
            // 关闭资源
            try {
                if (outputStream != null) outputStream.close();
            } catch (IOException e) {
                mainDataLogger.error("输出流关闭异常", e);
            }
            closeResources(reader, inputStream, connection);
        }

        return response.toString();
    }

    private String sendHttpsGetRequest(String apiUrl) {
        StringBuilder response = new StringBuilder();
        HttpsURLConnection connection = null;
        InputStream inputStream = null;
        BufferedReader reader = null;

        try {
            URL url = new URL(apiUrl);
            connection = (HttpsURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(5000);
            connection.setRequestProperty("Accept", "application/json");
            connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");

            int responseCode = connection.getResponseCode();
            inputStream = (responseCode == HttpsURLConnection.HTTP_OK) ?
                    connection.getInputStream() : connection.getErrorStream();

            if (responseCode != HttpsURLConnection.HTTP_OK) {
                response.append("公钥获取失败（").append(responseCode).append("）\n");
            }

            reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }

        } catch (IOException e) {
            mainDataLogger.error("GET请求异常", e);
            response.append("请求异常：").append(e.getMessage());
        } finally {
            closeResources(reader, inputStream, connection);
        }

        return response.toString();
    }

    // ---------------------- 工具方法 ----------------------

    private String extractPublicKey(String jsonResponse) {
        try {
            ApiResponse response = gson.fromJson(jsonResponse, ApiResponse.class);
            if (response != null && response.isSuccess() && response.getData() != null) {
                return response.getData().getPublicKey();
            } else {
                mainDataLogger.error("公钥提取失败：响应无效");
                return null;
            }
        } catch (Exception e) {
            mainDataLogger.error("公钥JSON解析异常", e);
            return null;
        }
    }

    private String encrypt(String password, String publicKey) throws Exception {
        byte[] decodedPublicKey = Base64.getDecoder().decode(publicKey);
        RSAPublicKey rsaPublicKey = (RSAPublicKey) KeyFactory.getInstance("RSA")
                .generatePublic(new X509EncodedKeySpec(decodedPublicKey));

        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, rsaPublicKey);

        byte[] inputBytes = password.getBytes(StandardCharsets.UTF_8);
        int inputLength = inputBytes.length;
        final int MAX_ENCRYPT_BLOCK = 117;
        int offSet = 0;
        byte[] resultBytes = new byte[0];
        byte[] cache;

        while (inputLength - offSet > 0) {
            if (inputLength - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(inputBytes, offSet, MAX_ENCRYPT_BLOCK);
                offSet += MAX_ENCRYPT_BLOCK;
            } else {
                cache = cipher.doFinal(inputBytes, offSet, inputLength - offSet);
                offSet = inputLength;
            }
            byte[] temp = new byte[resultBytes.length + cache.length];
            System.arraycopy(resultBytes, 0, temp, 0, resultBytes.length);
            System.arraycopy(cache, 0, temp, resultBytes.length, cache.length);
            resultBytes = temp;
        }

        return Base64.getEncoder().encodeToString(resultBytes);
    }

    private void closeResources(BufferedReader reader, InputStream inputStream, HttpsURLConnection connection) {
        try {
            if (reader != null) reader.close();
            if (inputStream != null) inputStream.close();
            if (connection != null) connection.disconnect();
        } catch (IOException e) {
            mainDataLogger.error("资源关闭异常", e);
        }
    }

    // ---------------------- 响应结果实体类 ----------------------

    public static class SyncResult {
        private Date startTime;
        private Date endTime;
        private boolean success;
        private TokenData tokenInfo;
        private SyncDetail syncDetail;
        private List<String> errors;

        // Getters and Setters
        public Date getStartTime() { return startTime; }
        public void setStartTime(Date startTime) { this.startTime = startTime; }
        public Date getEndTime() { return endTime; }
        public void setEndTime(Date endTime) { this.endTime = endTime; }
        public boolean isSuccess() { return success; }
        public void setSuccess(boolean success) { this.success = success; }
        public TokenData getTokenInfo() { return tokenInfo; }
        public void setTokenInfo(TokenData tokenInfo) { this.tokenInfo = tokenInfo; }
        public SyncDetail getSyncDetail() { return syncDetail; }
        public void setSyncDetail(SyncDetail syncDetail) { this.syncDetail = syncDetail; }
        public List<String> getErrors() { return errors; }
        public void setErrors(List<String> errors) { this.errors = errors; }
    }

    public static class SyncDetail {
        private int totalPages;
        private int totalRecords;
        private int successCount;
        private int failedCount;
        private List<String> errors;

        public SyncDetail() {
            this.successCount = 0;
            this.failedCount = 0;
            this.errors = new ArrayList<>();
        }

        // 计数方法
        public void incrementSuccessCount() { this.successCount++; }
        public void incrementFailedCount() { this.failedCount++; }

        // Getters and Setters
        public int getTotalPages() { return totalPages; }
        public void setTotalPages(int totalPages) { this.totalPages = totalPages; }
        public int getTotalRecords() { return totalRecords; }
        public void setTotalRecords(int totalRecords) { this.totalRecords = totalRecords; }
        public int getSuccessCount() { return successCount; }
        public int getFailedCount() { return failedCount; }
        public List<String> getErrors() { return errors; }
        public void setErrors(List<String> errors) { this.errors = errors; }
    }

    // ---------------------- 数据模型实体类 ----------------------

    private static class TokenRequest {
        private final String grant_type;
        private final String username;
        private final String password;
        private final String client_id;
        private final String client_secret;
        private final String public_key;

        public TokenRequest(String username, String encryptedPassword, String publicKey) {
            this.grant_type = FIXED_GRANT_TYPE;
            this.username = username;
            this.password = encryptedPassword;
            this.client_id = FIXED_CLIENT_ID;
            this.client_secret = FIXED_CLIENT_SECRET;
            this.public_key = publicKey;
        }

        // Getters
        public String getGrant_type() { return grant_type; }
        public String getUsername() { return username; }
        public String getPassword() { return password; }
        public String getClient_id() { return client_id; }
        public String getClient_secret() { return client_secret; }
        public String getPublic_key() { return public_key; }
    }

    private static class TokenResponse {
        private boolean success;
        private TokenData data;
        private String code;
        private String errMsg;

        // Getters
        public boolean isSuccess() { return success; }
        public TokenData getData() { return data; }
        public String getCode() { return code; }
        public String getErrMsg() { return errMsg; }
    }

    public static class TokenData {
        private String access_token;
        private String refresh_token;
        private long expires_in;
        private String token_type;

        // Getters
        public String getAccess_token() { return access_token; }
        public String getRefresh_token() { return refresh_token; }
        public long getExpires_in() { return expires_in; }
        public String getToken_type() { return token_type; }
    }

    private static class PersonSubsystemListRequest {
        private int pageNum = 1;
        private int pageSize = FIXED_PAGE_SIZE;
        private Integer maxRangeId;

        public PersonSubsystemListRequest(int pageNum, Integer maxRangeId) {
            this.pageNum = pageNum;
            this.maxRangeId = maxRangeId;
        }

        // Getters
        public int getPageNum() { return pageNum; }
        public int getPageSize() { return pageSize; }
        public Integer getMaxRangeId() { return maxRangeId; }
    }

    private static class PersonSubsystemListResponse {
        private boolean success;
        private PersonSubsystemData data;
        private String code;
        private String errMsg;

        // Getters
        public boolean isSuccess() { return success; }
        public PersonSubsystemData getData() { return data; }
        public String getCode() { return code; }
        public String getErrMsg() { return errMsg; }
    }

    private static class PersonSubsystemData {
        private PersonItem[] pageData;
        private int currentPage;
        private int totalPage;
        private int pageSize;
        private int totalRows;

        // Getters
        public PersonItem[] getPageData() { return pageData; }
        public int getCurrentPage() { return currentPage; }
        public int getTotalPage() { return totalPage; }
        public int getPageSize() { return pageSize; }
        public int getTotalRows() { return totalRows; }
    }

    private static class PersonItem {
        private int id;
        private String code;
        private String name;
        private int sex;
        private Long birthday;
        private int age;
        private String personType;
        private int isAdmin;
        private int paperType;
        private String paperTypeName;
        private String paperNumber;
        private String country;
        private int nation;
        private String nationName;
        private int departmentId;
        private int status;
        private String ownerCode;
        private int personIdentityId;
        private Department[] departmentList;
        private PersonBiosignature[] personBiosignatures;
        private String paperAddress;
        private String email;
        private String phone;

        // Getters
        public int getId() { return id; }
        public String getCode() { return code; }
        public String getName() { return name; }
        public int getSex() { return sex; }
        public Long getBirthday() { return birthday; }
        public int getAge() { return age; }
        public String getPersonType() { return personType; }
        public int getIsAdmin() { return isAdmin; }
        public int getPaperType() { return paperType; }
        public String getPaperTypeName() { return paperTypeName; }
        public String getPaperNumber() { return paperNumber; }
        public String getCountry() { return country; }
        public int getNation() { return nation; }
        public String getNationName() { return nationName; }
        public int getDepartmentId() { return departmentId; }
        public int getStatus() { return status; }
        public String getOwnerCode() { return ownerCode; }
        public int getPersonIdentityId() { return personIdentityId; }
        public Department[] getDepartmentList() { return departmentList; }
        public PersonBiosignature[] getPersonBiosignatures() { return personBiosignatures; }
        public String getPaperAddress() { return paperAddress; }
        public String getEmail() { return email; }
        public String getPhone() { return phone; }
    }

    private static class Department {
        private int departmentId;
        private int departmentType;
        private int status;

        // Getters
        public int getDepartmentId() { return departmentId; }
        public int getDepartmentType() { return departmentType; }
        public int getStatus() { return status; }
    }

    private static class PersonBiosignature {
        private int type;
        private String path;
        private int status;

        // Getters
        public int getStatus() { return status; }
        public int getType() { return type; }
        public String getPath() { return path; }
    }

    private static class ApiResponse {
        private boolean success;
        private Data data;
        private String code;
        private String errMsg;

        // Getters
        public boolean isSuccess() { return success; }
        public Data getData() { return data; }
    }

    private static class Data {
        private String publicKey;
        public String getPublicKey() { return publicKey; }
    }
}
